﻿using System;
using Devonline.Core;
using Devonline.Entity;
using Microsoft.EntityFrameworkCore;

namespace Devonline.Identity
{
    /// <summary>
    /// 重载的身份上下文, 提供字符串类型主键的默认实现
    /// </summary>
    public class SecurityIdentityDbContext : SecurityIdentityDbContext<User, Role, UserClaim, UserRole, UserLogin, RoleClaim, UserToken, Group, UserGroup, Level, Resource, AccessRule, AccessApply, AccessRecord, Secret, UserSecret, ResourceSecret, Parameter, Attachment, string>
    {
        public SecurityIdentityDbContext(DbContextOptions<IdentityDbContext> options) : base(options)
        {
        }
    }

    /// <summary>
    /// 重载的安全身份上下文
    /// </summary>
    /// <typeparam name="TUser"></typeparam>
    /// <typeparam name="TRole"></typeparam>
    /// <typeparam name="TUserClaim"></typeparam>
    /// <typeparam name="TUserRole"></typeparam>
    /// <typeparam name="TUserLogin"></typeparam>
    /// <typeparam name="TRoleClaim"></typeparam>
    /// <typeparam name="TUserToken"></typeparam>
    /// <typeparam name="TGroup"></typeparam>
    /// <typeparam name="TUserGroup"></typeparam>
    /// <typeparam name="TLevel"></typeparam>
    /// <typeparam name="TResource"></typeparam>
    /// <typeparam name="TAccessRule"></typeparam>
    /// <typeparam name="TAccessApply"></typeparam>
    /// <typeparam name="TAccessRecord"></typeparam>
    /// <typeparam name="TSecret"></typeparam>
    /// <typeparam name="TResourceSecret"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public class SecurityIdentityDbContext<TUser, TRole, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken, TGroup, TUserGroup, TLevel, TResource, TAccessRule, TAccessApply, TAccessRecord, TSecret, TUserSecret, TResourceSecret, TParameter, TAttachment, TKey> :
        IdentityDbContext<TUser, TRole, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken, TGroup, TUserGroup, TLevel, TResource, TAccessRule, TAccessApply, TAccessRecord, TParameter, TAttachment, TKey>
        where TUser : User<TKey>
        where TRole : Role<TKey>
        where TUserClaim : UserClaim<TKey>
        where TUserRole : UserRole<TKey>
        where TUserLogin : UserLogin<TKey>
        where TRoleClaim : RoleClaim<TKey>
        where TUserToken : UserToken<TKey>
        where TGroup : Group<TKey>
        where TUserGroup : UserGroup<TKey>
        where TLevel : Level<TKey>
        where TResource : Resource<TKey>
        where TAccessRule : AccessRule<TKey>
        where TAccessApply : AccessApply<TKey>
        where TAccessRecord : AccessRecord<TKey>
        where TParameter : Parameter<TKey>
        where TAttachment : Attachment<TKey>
        where TSecret : Secret<TKey>
        where TUserSecret : UserSecret<TKey>
        where TResourceSecret : ResourceSecret<TKey>
        where TKey : IEquatable<TKey>, IConvertible
    {
        public SecurityIdentityDbContext(DbContextOptions options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.Entity<TSecret>(b =>
            {
                b.Property(x => x.State).HasDefaultValue(DataState.Available);
                b.Property(x => x.AssignType).HasDefaultValue(AssignType.User);
                b.Property(x => x.CharacterEncodingAlgorithm).HasDefaultValue(EncryptionAlgorithm.Base64);
                b.Property(x => x.HashAlgorithm).HasDefaultValue(ValidationAlgorithm.HMACSHA256);
                b.Property(x => x.SymmetricAlgorithm).HasDefaultValue(SymmetricAlgorithm.AES_256_CBC);
                b.Property(x => x.AsymmetricAlgorithm).HasDefaultValue(EncryptionAlgorithm.RSA);
            });

            builder.Entity<TUserSecret>(b => b.Property(x => x.State).HasDefaultValue(DataState.Available));
            builder.Entity<TResourceSecret>(b => b.Property(x => x.State).HasDefaultValue(DataState.Available));
        }

        #region identity core entities
        /// <summary>
        /// Secret
        /// </summary>
        public virtual DbSet<TSecret> Secrets { get; set; }
        /// <summary>
        /// UserSecret
        /// </summary>
        public virtual DbSet<TUserSecret> UserSecrets { get; set; }
        /// <summary>
        /// ResourceSecret
        /// </summary>
        public virtual DbSet<TResourceSecret> ResourceSecrets { get; set; }
        #endregion
    }
}
